package com.errol.generic.http;

import java.util.concurrent.Future;

/**
 * 灵活、安全、可扩展的 HttpService
 * 使用建造者模式构建 http 执行计划，各种请求参数都可以灵活配置
 * 内部捕获输出异常日志，返回请求失败，不会向调用者抛出异常
 * 方便扩展新的请求和响应类型，支持灵活切换第三方 HTTP 客户端工具包
 * <p>
 * 使用 {@link HttpBuilder} 构建 HttpPlan 执行计划，构建过程分为 5 个部分：
 * HttpBuilder：设置请求 url，请求方法，超时时间等参数；由 HttpBuilder.builder() 创建；
 * HttpHeaderBuilder：设置 http header 中的参数；由 httpBuilder.useXxx() 系列方法创建；
 * HttpXxxBodyBuilder：设置 http requestBody 中的参数，不同的请求体编码格式需要对应的 HttpXxxBodyBuilder；由 httpHeaderBuilder.sendXxxData() 系列方法创建；
 * HttpXxxResultBuilder：设置 http responseBody 中的响应类型，不同的响应体编码格式需要对应的 HttpXxxResultBuilder；由 httpXxxBodyBuilder.expectXxxOfYyy() 系列方法创建；
 * HttpPlan：Http 执行计划，定义请求参数和响应参数，由 {@link HttpService} 同步或异步执行；由 httpXxxResultBuilder.build() 方法创建；
 * 除了转构建过程的 useXxx() sendXxxData() expectXxxOfYyy() 系列方法，其他的参数配置方法都是 setXxx() 或 addXxx()；
 * Http 构建执行过程中的异常已经由 {@link HttpLogger} 统一处理，调用者只需根据 {@link HttpResult} 判断请求成功与否；
 * json 序列化与反序列化都使用 ObjectMapper ，且只看 property ，使用 {@link com.fasterxml.jackson.annotation.JsonProperty} 注解映射不同的 javaBean 属性和 jsonStr 属性
 *
 * @author zhang xiao bin
 * @version v1.0
 * @date 2020/10/10
 * @since v
 **/
public interface HttpService {

    /**
     * 获取 HttpBuilder
     *
     * @param url 请求地址
     * @return HttpBuilder
     */
    HttpBuilder builder(String url);

    /**
     * 执行 HTTP 请求，示例: httpService.execute(httpService.builder(url).addXxx().setXxx()...build())
     *
     * @param httpPlan 由 HttpBuilder 构建的 http 执行计划
     * @param <T>      请求成功时的泛型类型
     * @return HttpResult<T>
     */
    <T> HttpResult<T> execute(HttpBuilder.HttpPlan<T> httpPlan);

    /**
     * 异步执行 HTTP 请求，即异步执行 execute
     *
     * @param httpPlan 由 HttpBuilder 构建的 http 执行计划
     * @param <T>      请求成功时的泛型类型
     * @return HttpResult<T>
     */
    <T> Future<HttpResult<T>> submit(HttpBuilder.HttpPlan<T> httpPlan);

}
